home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / console / svgatext.3 / svgatext / SVGATextMode-1.3 / XFREE / common_hw / Ti3026clk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-29  |  6.0 KB  |  213 lines

  1. /* $XFree86: xc/programs/Xserver/hw/xfree86/common_hw/Ti3026clk.c,v 3.2 1995/07/01 10:49:07 dawes Exp $ */
  2. /*
  3.  * Copyright 1995 The XFree86 Project, Inc
  4.  *
  5.  * programming the on-chip clock on the Ti3026, derived from the
  6.  * S3 gendac code by Jon Tombs
  7.  * Harald Koenig <koenig@tat.physik.uni-tuebingen.de>
  8.  */
  9.  
  10. #include "Ti302X.h" 
  11. #include "compiler.h"
  12. #define NO_OSLIB_PROTOTYPES
  13. #include "xf86_OSlib.h"
  14. #include <math.h>
  15.  
  16. #if NeedFunctionPrototypes
  17. static void
  18. s3ProgramTi3026Clock(int clk, unsigned char n, unsigned char m, 
  19.              unsigned char p, unsigned char ln, unsigned char lm, 
  20.              unsigned char lp, unsigned char lq)
  21. #else
  22. static void
  23. s3ProgramTi3026Clock(clk, n, m, p, ln, lm, lp, lq)
  24. int clk;
  25. unsigned char n;
  26. unsigned char m;
  27. unsigned char p;
  28. unsigned char ln;
  29. unsigned char lm;
  30. unsigned char lp;
  31. unsigned char lq;
  32. #endif
  33. {
  34.    int tmp;
  35.    /*
  36.     * Reset the clock data index
  37.     */
  38.    s3OutTi3026IndReg(TI_PLL_CONTROL, 0x00, 0x00);
  39.  
  40.    if (clk != TI_MCLK_PLL_DATA) {
  41.       /*
  42.        * Now output the clock frequency
  43.        */
  44.       s3OutTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, (n & 0x3f) | 0x80);
  45.       s3OutTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, (m & 0x3f) );
  46.       tmp = s3InTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA) & 0x40;
  47.       s3OutTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, (p & 3) | tmp | 0xb0);
  48.  
  49.       /* wait until PLL is locked */
  50.       for (tmp=0; tmp<10000; tmp++) 
  51.      if (s3InTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA) & 0x40) 
  52.         break;
  53.  
  54.       /*
  55.        * And now set up the loop clock for RCLK
  56.        */
  57.       s3OutTi3026IndReg(TI_LOOP_CLOCK_PLL_DATA, 0x00, (ln & 0x3f) | 0x80);
  58.       s3OutTi3026IndReg(TI_LOOP_CLOCK_PLL_DATA, 0x00, (lm & 0x3f));
  59.       s3OutTi3026IndReg(TI_LOOP_CLOCK_PLL_DATA, 0x00, (lp & 3) | 0xf0);
  60.       s3OutTi3026IndReg(TI_MCLK_LCLK_CONTROL, 0xf8, lq);
  61.  
  62.       /* select pixel clock PLL as dot clock soure */
  63.       s3OutTi3026IndReg(TI_INPUT_CLOCK_SELECT, 0x00, TI_ICLK_PLL);
  64.    }
  65.    else {
  66.       int pn, pm, pp, csr;
  67.  
  68.       /* select pixel clock PLL as dot clock soure */
  69.       csr = s3InTi3026IndReg(TI_INPUT_CLOCK_SELECT);
  70.       s3OutTi3026IndReg(TI_INPUT_CLOCK_SELECT, 0x00, TI_ICLK_PLL);
  71.  
  72.       /* save the old dot clock PLL settings */
  73.       s3OutTi3026IndReg(TI_PLL_CONTROL, 0x00, 0x00);
  74.       pn = s3InTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA);
  75.       s3OutTi3026IndReg(TI_PLL_CONTROL, 0x00, 0x01);
  76.       pm = s3InTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA);
  77.       s3OutTi3026IndReg(TI_PLL_CONTROL, 0x00, 0x02);
  78.       pp = s3InTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA);
  79.  
  80.       /* programm dot clock PLL to new MCLK frequency */
  81.       s3OutTi3026IndReg(TI_PLL_CONTROL, 0x00, 0x00);
  82.       s3OutTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, (n & 0x3f) | 0x80);
  83.       s3OutTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, (m & 0x3f) );
  84.       tmp = s3InTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA) & 0x40;
  85.       s3OutTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, (p & 3) | tmp | 0xb0);
  86.  
  87.       /* wait until PLL is locked */
  88.       for (tmp=0; tmp<10000; tmp++)
  89.      if (s3InTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA) & 0x40) 
  90.         break;
  91.  
  92.       /* switch to output dot clock on the MCLK terminal */
  93.       s3OutTi3026IndReg(0x39, 0xe7, 0x00);
  94.       s3OutTi3026IndReg(0x39, 0xe7, 0x08);
  95.       
  96.       /* Set MCLK */
  97.       s3OutTi3026IndReg(TI_PLL_CONTROL, 0x00, 0x00);
  98.       s3OutTi3026IndReg(TI_MCLK_PLL_DATA, 0x00, (n & 0x3f) | 0x80);
  99.       s3OutTi3026IndReg(TI_MCLK_PLL_DATA, 0x00, (m & 0x3f));
  100.       s3OutTi3026IndReg(TI_MCLK_PLL_DATA, 0x00, (p & 3) | 0xb0);
  101.  
  102.       /* wait until PLL is locked */
  103.       for (tmp=0; tmp<10000; tmp++) 
  104.      if (s3InTi3026IndReg(TI_MCLK_PLL_DATA) & 0x40) 
  105.         break;
  106.  
  107.       /* switch to output MCLK on the MCLK terminal */
  108.       s3OutTi3026IndReg(0x39, 0xe7, 0x10);
  109.       s3OutTi3026IndReg(0x39, 0xe7, 0x18);
  110.  
  111.       /* restore dot clock PLL */
  112.       s3OutTi3026IndReg(TI_PLL_CONTROL, 0x00, 0x00);
  113.       s3OutTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, pn);
  114.       s3OutTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, pm);
  115.       s3OutTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, pp);
  116.  
  117.       /* wait until PLL is locked */
  118.       for (tmp=0; tmp<10000; tmp++) 
  119.      if (s3InTi3026IndReg(TI_PIXEL_CLOCK_PLL_DATA) & 0x40) 
  120.         break;
  121.       s3OutTi3026IndReg(TI_INPUT_CLOCK_SELECT, 0x00, csr);
  122.    }
  123. }
  124.  
  125. #if NeedFunctionPrototypes
  126. void Ti3026SetClock(long freq, int clk, int bpp)
  127. #else
  128. void
  129. Ti3026SetClock(freq, clk, bpp)
  130. long freq;
  131. int clk;
  132. int bpp;
  133. #endif
  134. {
  135.    double ffreq;
  136.    int n, p, m;
  137.    int ln, lp, lm, lq, lk, z;
  138.    int best_n=32, best_m=32;
  139.    double  diff, mindiff;
  140.    
  141. #define FREQ_MIN   13767  /* ~110000 / 8 */
  142. #define FREQ_MAX  220000
  143.  
  144.    if (freq < FREQ_MIN)
  145.       ffreq = FREQ_MIN / 1000.0;
  146.    else if (freq > FREQ_MAX)
  147.       ffreq = FREQ_MAX / 1000.0;
  148.    else
  149.       ffreq = freq / 1000.0;
  150.    
  151.  
  152.  
  153.    /* work out suitable timings */
  154.  
  155.    /* pick the right p value */
  156.  
  157.    for(p=0; p<4 && ffreq < 110.0; p++)
  158.       ffreq *= 2;
  159.    
  160.    /* now 110.0 <= ffreq <= 220.0 */   
  161.    
  162.    ffreq /= TI_REF_FREQ;
  163.    
  164.    /* now 7.6825 <= ffreq <= 15.3650 */
  165.    /* the remaining formula is  ffreq = (65-m)*8 / (65-n) */
  166.    
  167.    
  168.    mindiff = ffreq;
  169.    
  170.    for (n=63; n >= 65 - (int)(TI_REF_FREQ/0.5); n--) {
  171.       m = 65 - (int)(ffreq * (65-n) / 8.0 + 0.5);
  172.       if (m < 1)
  173.      m = 1;
  174.       else if (m > 63) 
  175.      m = 63;
  176.       
  177.       diff = ((65-m) * 8) / (65.0-n) - ffreq;
  178.       if (diff<0)
  179.      diff = -diff;
  180.       
  181.       if (diff < mindiff) {
  182.      mindiff = diff;
  183.      best_n = n;
  184.      best_m = m;
  185.       }
  186.    }
  187.  
  188. #ifdef DEBUG
  189.    ErrorF("clk %d, setting to %f, n %02x %d, m %02x %d, p %d\n", clk,
  190.       8.0/(1 << p)*((65.0-best_m)/(65-best_n)) * TI_REF_FREQ,
  191.       best_n, best_n, best_m, best_m, p);
  192. #endif
  193.  
  194.    ln = 65 - 2 * 64 / 8 / bpp;
  195.    lm = 63;
  196.    lk = 1;
  197.    z = (100 * 110000 * (65-ln)) / (lk * freq);
  198.    if (z > 1600) {
  199.       lp = 3;
  200.       lq = (z-1600) / 1600 + 1; /* smallest q greater (z-16)/16 */
  201.    }
  202.    else { /* largest p less then log2(z) */
  203.       for (lp=0; z > (200 << lp); lp++) ;
  204.       lq = 0;
  205.    }
  206.  
  207. #ifdef DEBUG
  208.    ErrorF("bpp %d  ln %2d  lm %2d  lp %2d  lq %2d\n",bpp,ln,lm,lp,lq);
  209. #endif
  210.  
  211.    s3ProgramTi3026Clock(clk, best_n, best_m, p, ln, lm, lp, lq);
  212. }
  213.